import re
import calendar
from datetime import datetime

from dateutil.tz import *
from paste.httpexceptions import HTTPNotFound

from brightcontent.util import UrlDispatch


class WsgiApplication(object):
    def __init__(self, application, store, app_conf):
        self.store = store
        self.application = application
        self.m = UrlDispatch(self.urls)
        self.entries_per_page = int(app_conf.get('entries_per_page', 10))

    def __call__(self, environ, start_response):
        #import pprint; pprint.pprint(environ)
        #Umm, why the default? If we don't have a PATH_INFO, isn't something horribly broken?
        path_info = environ.get('PATH_INFO', '/')
        # FIXME: this is just a workaround for a paste bug
        if path_info == '': path_info = '/'
        func, query_dict = self.m.match(path_info)
        if func:
            return func(self, environ, start_response, **query_dict)
        else:
            return self.application(environ, start_response)

    #Unused
    #def get_by_type(self, environ, start_response, args):
    #    if args['type'] == 'comment':
    #        entries = self.store.get_entries()

    def return_entries(self, environ, start_response, entries):
        start_response('200 OK', [('Content-type', 'application/atom+xml')])
        is_atom_request = environ.get('PATH_INFO', '').endswith('index.atom')
        environ['brightcontent.render'] = not is_atom_request
        if entries:
            feed = self.store.assemble_feed(entries)
            return [feed]
        raise HTTPNotFound()

    def specific(self, environ, start_response, year=0, month=0, day=0, slug=None, **etc):
        year, month, day = int(year), int(month), int(day)
        lower_date = datetime(year, month, day, 0, 0, 0, tzinfo=tzutc()) 
        upper_date = datetime(year, month, day, 23, 59, 59, tzinfo=tzutc())
        entries = self.store.get_entries(lower_date=lower_date,
                upper_date=upper_date, slug=slug)
        return self.return_entries(environ, start_response, entries)

    def month(self, environ, start_response, year=0, month=0, **etc):
        year, month = int(year), int(month)
        lower_date = datetime(year, month, 1, tzinfo=tzutc())
        upper_date = datetime(year, month, calendar.monthrange(year, month)[1], tzinfo=tzutc())
        entries = self.store.get_entries(lower_date=lower_date,
                upper_date=upper_date)
        return self.return_entries(environ, start_response, entries)

    def year(self, environ, start_response, year=0, **etc):
        year = int(year)
        lower_date = datetime(year, 1, 1, tzinfo=tzutc())
        upper_date = datetime(year, 12, 31, tzinfo=tzutc())
        entries = self.store.get_entries(lower_date=lower_date,
                upper_date=upper_date)
        return self.return_entries(environ, start_response, entries)

    def page(self, environ, start_response, page=1, **etc):
        limit = self.entries_per_page
        offset = (page-1) * limit
        entries = self.store.get_entries(offset=offset, limit=limit)
        return self.return_entries(environ, start_response, entries)

    def index(self, environ, start_response, **etc):
        return self.page(environ, start_response, 1)

    urls = (
            #Non-slug full date check has to be on top because it's most specific (think of the index.atom case)
            (r'/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})(?P<atom>/index\.atom)?', specific),
            (r'/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[a-z0-9\-\;\)\:]+)(?P<atom>/index\.atom)?', specific),
            (r'/(?P<year>\d{4})/(?P<month>\d{1,2})(?P<atom>/index\.atom)?', month),
            (r'/(?P<year>\d{4})(?P<atom>/index\.atom)?', year),
            (r'/(?P<atom>index\.atom)?', index)
        )



